#include "../common/Log.hpp"
#include "../common/util.hpp"

using namespace util_ns;
using namespace LogModule_ns;

/* ******************************
 * question描述字段要包含的信息：
 * 问题的编号(primary key)
 * 问题的标题
 * 问题的难度
 * 问题的资源限制
 * 问题的文字描述
 * 预留给用户的代码
 * 问题的测试用例代码
 ******************************* */
class QuestionDescribe
{
public:
    using ptr = std::shared_ptr<QuestionDescribe>;
    QuestionDescribe(std::vector<std::string> &source)
    {
        id = source[0];
        title = source[1];
        star = source[2];
        cpu_load = std::stoi(source[3]);
        mem_load = std::stoi(source[4]);
        desc = source[5];
        code = source[6];
        tail = source[7];
    }
    ~QuestionDescribe() = default;
    std::string id;
    std::string title;
    std::string star;
    int cpu_load;
    int mem_load;
    std::string desc;
    std::string code;
    std::string tail;
};

// 所有题目的综合描述字段的路径和名字
static std::string lib_path("./questions/");
static std::string lib_name("./questions/questions.list");

class QuestionsModule
{
public:
    void GetFromFile(std::vector<std::string> &source)
    {
        std::string id = source[0];
        std::string lib = lib_path + id + '/';

        std::string desc;
        util_ns::FileUtil::readFile(lib + "desc.txt", desc, true);
        std::string code;
        util_ns::FileUtil::readFile(lib + "header.cpp", code, true);
        std::string tail;
        util_ns::FileUtil::readFile(lib + "tail.cpp", tail, true);
        source.emplace_back(desc);
        source.emplace_back(code);
        source.emplace_back(tail);
    }
    QuestionsModule()
    {
        load();
        DLOG(INFO) << "加载题库成功!";
    }
    void load()
    {
        std::ifstream in(lib_name);
        if (!in.is_open())
        {
            DLOG(FATAL) << "所有题目的综合描述字段的路径有误！！！";
            std::abort();
        }
        std::string str;
        while (std::getline(in, str))
        {
            //DLOG(DEBUG) << "进入查看库的getline循环";
            std::vector<std::string> source;
            // 提取行信息进行构造对象
            //DLOG(DEBUG) << "开始对行信息进行解析";
            util_ns::StringUtil::SplitString(str, source, " ");
            //DLOG(DEBUG) << "对行信息解析完毕，开始判断题目的描述字段是否正确";
            // 填充代码信息
            if (source.size() != 5)
            {
                DLOG(WARNING) << "题目的描述字段有错误！";
                continue;
            }
            //DLOG(DEBUG) << "开始填充代码信息";

            GetFromFile(source);

            // 开始填充
            //DLOG(DEBUG) << "开始向_questions压入";

            QuestionDescribe::ptr oj_desc = std::make_shared<QuestionDescribe>(source);
            _questions.emplace(oj_desc->id, oj_desc);
        }
    }
    bool GetAllQuestions(std::vector<QuestionDescribe::ptr> &out)
    {
        if (_questions.size() == 0)
        {
            DLOG(ERROR) << "用户获取题库失败" << "\n";
            return false;
        }
        for (const auto &q : _questions)
        {
            out.push_back(q.second);
        }

        return true;
    }
    bool GetOneQuestion(const std::string &number, QuestionDescribe::ptr &q)
    {
        const auto &iter = _questions.find(number);
        if (iter == _questions.end())
        {
            DLOG(ERROR) << "用户获取题目失败, 题目编号: " << number << "\n";
            return false;
        }
        q = iter->second;
        return true;
    }
    void Modify()
    {
        // TODO
    }

private:
    // 这里不使用int,方便后期删除指定id
    std::unordered_map<std::string, QuestionDescribe::ptr> _questions;
};